package filter;

import org.apache.dubbo.common.constants.CommonConstants;
import org.apache.dubbo.common.extension.Activate;
import org.apache.dubbo.rpc.*;

import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

@Activate({CommonConstants.CONSUMER})
public class TpMontiorFilter implements Filter, Runnable {

    public TpMontiorFilter() {
        Executors.newSingleThreadScheduledExecutor()
                .scheduleWithFixedDelay(this, 5, 5, TimeUnit.SECONDS);
    }

    Map<String, List<Map<String, Object>>> methodInfos = new ConcurrentHashMap<>();

    @Override
    public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {
        long startTime = System.currentTimeMillis();
        Result result = invoker.invoke(invocation);
        long endTime = System.currentTimeMillis() - startTime;
        Map<String,Object> methodInfo = new HashMap<>();
        //方法的执行时间 结束时间
        String methodName = invocation.getMethodName();
        methodInfo.put("methodName",methodName);
        methodInfo.put("taskTime",endTime);
        methodInfo.put("endTime",System.currentTimeMillis());
        List<Map<String, Object>> maps = methodInfos.get(methodName);
        if(Objects.isNull(maps)){
            List<Map<String, Object>> list = new ArrayList<>();
            list.add(methodInfo);
            methodInfos.put(methodName,list);
        }else {
            methodInfos.get(methodName).add(methodInfo);
        }


        return result;
    }

    @Override
    public void run() {

        //遍历计算
        Set<Map.Entry<String, List<Map<String, Object>>>> entries = this.methodInfos.entrySet();
        for (Map.Entry<String, List<Map<String, Object>>> entry : entries) {

            //获取方法集合
            List<Map<String, Object>> methods = entry.getValue();
            long  endTime = System.currentTimeMillis();
            long  startTime = System.currentTimeMillis() - 60000;
            //过滤出 执行时间在一分钟内的
            List<Map<String, Object>> sortList = methods.stream().filter((e) -> {
                long endTime1 = (long) e.get("endTime");
                if(endTime1>= startTime && endTime1<=endTime) {
                    return true;
                }else {
                    return false;
                }
            }).sorted(
                    (e1,e2)->{
                        //根据方法耗时进行排序
                      long e1TaskTime = (long)  e1.get("taskTime");
                      long e2TaskTime = (long)  e2.get("taskTime");
                      if(e1TaskTime>e2TaskTime){
                            return 1;
                      }else if(e1TaskTime<e2TaskTime){
                          return  -1;
                      }else {
                          return 0;
                      }
                    }

            ).collect(Collectors.toList());
            int size = sortList.size();
            //获取 0.9 和 0.99
            sortList.get((int) (size * 0.9)).get("methodName");
            sortList.get((int) (size * 0.99)).get("methodName");

        }


    }



}
